// Fill out your copyright notice in the Description page of Project Settings.



#include "SSlateDemoSlateDrawPaintWidget.h"
#include "SlateOptMacros.h"
#include "../Private/Framework/Testing/TestStyle.h"
#include "Rendering/SlateLayoutTransform.h"
#include "Styling/SlateBrush.h"
#include "UI/Style/SlateDemoWidgetStyle.h"
#include "UI/Style/SlateDemoManager.h"


BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlateDemoSlateDrawPaintWidget::Construct(const FArguments& InArgs)
{
	FontScale = 1.0;

	ChildSlot
	[
		SNew(SVerticalBox)
		+SVerticalBox::Slot()
		.FillHeight(1.0f)
		[
			SNew(SCustomPaintWidget)
			.OnPaintHandler(this, &SSlateDemoSlateDrawPaintWidget::TestTextElement)//绘制文本
		]
		+ SVerticalBox::Slot()
			.FillHeight(1)
			[
				SNew(SCustomPaintWidget)
				.OnPaintHandler(this, &SSlateDemoSlateDrawPaintWidget::TestGradientElement)//创建渐变色
			]
		+ SVerticalBox::Slot()
			.FillHeight(1)
			[
				SNew(SCustomPaintWidget)
				.OnPaintHandler(this, &SSlateDemoSlateDrawPaintWidget::TestSplineElement)//绘制线条
			]
		+ SVerticalBox::Slot()
			.FillHeight(.5f)
			[
				SNew(SCustomPaintWidget)
				.OnPaintHandler(this, &SSlateDemoSlateDrawPaintWidget::TestRotation)//让图形自转和公转
			]
		+ SVerticalBox::Slot()
			.FillHeight(3)
			[
				SNew(SCustomPaintWidget)
				.OnPaintHandler(this, &SSlateDemoSlateDrawPaintWidget::TestCustomVerts)//自定义图形
			]
	];
	
}

SSlateDemoSlateDrawPaintWidget::SSlateDemoSlateDrawPaintWidget()
{
	CenterRotation = 0;
	OuterRotation = 0;
	ToolbarStyle = &SlateDemoManager::Get().GetWidgetStyle<FSlateDemoStyle>("SlateDemoStyle_BP");
}

END_SLATE_FUNCTION_BUILD_OPTIMIZATION

void SSlateDemoSlateDrawPaintWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	CenterRotation += InDeltaTime * .3;
	if (CenterRotation > 2 * PI)
	{
		CenterRotation -= 2 * PI;
	}

	OuterRotation += (InDeltaTime * 1.5);
	if (OuterRotation > 2 * PI)
	{
		OuterRotation -= 2 * PI;
	}
}

int32 SSlateDemoSlateDrawPaintWidget::TestTextElement(const FOnPaintHandlerParams& InParams)
{
	const FText Text = FText::FromString("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789XH666");
	uint32 FontSize = 14;//
	FSlateFontInfo FontInfo = FCoreStyle::GetDefaultFontStyle("Regular", FontSize);
	FontInfo.OutlineSettings.OutlineColor = FLinearColor::Blue;//蓝色的外轮廓
	FontInfo.OutlineSettings.OutlineSize = 2;

	FSlateDrawElement::MakeText(//绘制字符
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToPaintGeometry(FVector2D(0, 0), InParams.Geometry.GetLocalSize(), FontScale),//坐标大小
		Text.ToString(),//字符串
		FontInfo,//字体信息
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,//绘制效果
		FColor(255, 255, 255)//字体的颜色
	);

	return InParams.Layer;
}

int32 SSlateDemoSlateDrawPaintWidget::TestGradientElement(const FOnPaintHandlerParams& InParams)
{
	TArray<FSlateGradientStop> GradientStops;

	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * .1f, 0), FColor::Red));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * .2f, 0), FColor::Orange));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * .3f, 0), FColor::Yellow));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * 0.4f, 0), FColor::Green));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * 0.5f, 0), FColor::Cyan));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * 0.6f, 0), FColor::Blue));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * 0.7f, 0), FColor::Purple));
	GradientStops.Add(FSlateGradientStop(FVector2D(InParams.Geometry.GetLocalSize().X * 0.9f, 0), FColor::Emerald));

	FSlateDrawElement::MakeGradient(//绘制渐变色
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToPaintGeometry(),
		GradientStops,
		Orient_Vertical,//水平
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect
	);

	return InParams.Layer;
}

void SSlateDemoSlateDrawPaintWidget::DrawLineRedress(FVector2D& BeginLine, FVector2D& EndLine)
{
	//我也很奇怪,为什么要这样,但必须要这样你才能得到你想要的正确的坐标

	if (BeginLine.X == EndLine.X)
	{	//  ↑
		if (BeginLine.Y > EndLine.Y)
		{
			EndLine.Y -= 1;
		}
		//	↓
		else if(BeginLine.Y < EndLine.Y)
		{
			BeginLine.Y += 1;
		}
	}
	else if (BeginLine.Y == EndLine.Y)
	{
		//←
		if (BeginLine.X > EndLine.X)
		{
			EndLine.X += 1;
		}
		//→
		else if (BeginLine.X < EndLine.X)
		{
			BeginLine.X -= 1;
		}
	}
	else if (BeginLine.X < EndLine.X)
	{
		// ↘
		if (BeginLine.Y < EndLine.Y)
		{
			BeginLine.X -= 1;
			BeginLine.Y -= 1;
		}
		// ↗
		else if (BeginLine.Y > EndLine.Y)
		{
			BeginLine.X -= 1;
			EndLine.Y -= 1;
		}
	}
	else if (BeginLine.X > EndLine.X)
	{
		//↙
		if (BeginLine.Y < EndLine.Y)
		{
			BeginLine.Y -= 1;
			EndLine.X -= 1;
		}
		//↖
		else if (BeginLine.Y > EndLine.Y)
		{
			EndLine.X += 1;
			EndLine.Y += 1;
		}
	}
}


int32 SSlateDemoSlateDrawPaintWidget::TestSplineElement(const FOnPaintHandlerParams& InParams)
{
//#pragma region MakeSpline(绘制样条曲线)
//	const FVector2D Start(10, 10);
//	const FVector2D StartDir(InParams.Geometry.GetLocalSize().X * 1000 / 600, 0);
//	const FVector2D End(InParams.Geometry.GetLocalSize().X / 4, InParams.Geometry.GetLocalSize().Y - 10);
//	const FVector2D EndDir(InParams.Geometry.GetLocalSize().X * 1000 / 600, 0);
//
//	FSlateDrawElement::MakeSpline(//样条曲线
//		InParams.OutDrawElements,
//		InParams.Layer,
//		InParams.Geometry.ToPaintGeometry(),
//		Start, StartDir,
//		End, EndDir,
//		InParams.Geometry.Scale,
//		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
//		FColor::White
//	);
//#pragma endregion

#pragma region MakeLines(绘制锯齿线)

	TArray<FVector2D> ceshi;
	for (int i = 0; i < 10; i++)
	{

			ceshi.Empty();
			ceshi.Add(FVector2D(0, i*10));
			ceshi.Add(FVector2D( 100, i * 10));

			FSlateDrawElement::MakeLines(//绘制线条
				InParams.OutDrawElements,
				InParams.Layer,
				InParams.Geometry.ToPaintGeometry(),
				ceshi,
				InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
				FColor::White,
				false,
				InParams.Geometry.Scale
			);

			ceshi.Empty();
			ceshi.Add(FVector2D(i * 10, 0));
			ceshi.Add(FVector2D(i * 10, 100));

			FSlateDrawElement::MakeLines(//绘制线条
				InParams.OutDrawElements,
				InParams.Layer,
				InParams.Geometry.ToPaintGeometry(),
				ceshi,
				InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
				FColor::White,
				false,
				InParams.Geometry.Scale
			);

	}


	//ceshi.Empty();
	//ceshi.Add(FVector2D(10.0, 20.0));
	//ceshi.Add(FVector2D(20.0, 20.0));
	//FSlateDrawElement::MakeLines(//绘制线条
	//	InParams.OutDrawElements,
	//	InParams.Layer,
	//	InParams.Geometry.ToPaintGeometry(),
	//	ceshi,
	//	InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
	//	FColor::Blue,
	//	false,
	//	InParams.Geometry.Scale
	//);

	ceshi.Empty();
	FVector2D beginLine = FVector2D(20.0, 0.0);
	FVector2D EndLine = FVector2D(10.0, 10.0);
	DrawLineRedress(beginLine, EndLine);
	ceshi.Add(beginLine);
	ceshi.Add(EndLine);
	FSlateDrawElement::MakeLines(//绘制线条
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToPaintGeometry(),
		ceshi,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
		FColor::Red,
		false,
		InParams.Geometry.Scale
	);

	//ceshi.Empty();
	//ceshi.Add(FVector2D(20.0, 10.0));
	//ceshi.Add(FVector2D(20.0, 20.0));
	//FSlateDrawElement::MakeLines(//绘制线条
	//	InParams.OutDrawElements,
	//	InParams.Layer,
	//	InParams.Geometry.ToPaintGeometry(),
	//	ceshi,
	//	InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
	//	FColor::Red,
	//	false,
	//	InParams.Geometry.Scale
	//);
	//ceshi.Empty();
	//ceshi.Add(FVector2D(10, 0));
	//ceshi.Add(FVector2D(5, 5));
	//FSlateDrawElement::MakeLines(//绘制线条
	//	InParams.OutDrawElements,
	//	InParams.Layer,
	//	InParams.Geometry.ToPaintGeometry(),
	//	ceshi,
	//	InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
	//	FColor::Green,
	//	false,
	//	InParams.Geometry.Scale
	//);

	FVector2D LineStart = FVector2D(InParams.Geometry.GetLocalSize().X / 4, 10.0f);

	TArray<FVector2D> LinePoints;
	TArray<FLinearColor> LineColors;
	LinePoints.Add(LineStart); LineColors.Add(FLinearColor::Red);
	LinePoints.Add(LineStart + FVector2D(100.0f, 50.0f));
	LinePoints.Add(LineStart + FVector2D(200.0f, 10.0f));
	LinePoints.Add(LineStart + FVector2D(300.0f, 50.0f));
	LinePoints.Add(LineStart + FVector2D(400.0f, 10.0f));


	FSlateDrawElement::MakeLines(//绘制线条
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToPaintGeometry(),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
		FColor::White,
		true,
		InParams.Geometry.Scale
	);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 10)),//y轴偏移
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
		FColor::White,
		true,
		2 * InParams.Geometry.Scale//粗度
	);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 20)),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
		FColor::White,
		true,
		3 * InParams.Geometry.Scale
	);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 34)),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
		FColor::White,
		true,
		4 * InParams.Geometry.Scale
	);


#pragma endregion
#pragma region MakeLines(绘制波浪线)
	LineStart = LinePoints[LinePoints.Num() - 1] + FVector2D(50, 10);
	LinePoints.Empty();

	static float CurTime = 0;
	CurTime += FSlateApplication::Get().GetDeltaTime();//一个时间增量
	CurTime = FMath::Fmod(CurTime, 2 * PI);
	for (float I = 0; I < 10 * PI; I += .1f)//绘制SIN线条的10个点
	{
		LinePoints.Add(LineStart + FVector2D(I * 15, 15 * FMath::Sin(I + CurTime)));//根据时间增量来画出SIN线条,这样看起来就像再动了
	}

	static FColor Color = FColor::MakeRandomColor();
	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer + 1,
		InParams.Geometry.ToPaintGeometry(),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::NoPixelSnapping : ESlateDrawEffect::NoPixelSnapping | ESlateDrawEffect::DisabledEffect,
		Color,
		true,
		InParams.Geometry.Scale);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 10)),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::NoPixelSnapping : ESlateDrawEffect::NoPixelSnapping | ESlateDrawEffect::DisabledEffect,
		Color,
		true,
		2 * InParams.Geometry.Scale);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 20)),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::NoPixelSnapping : ESlateDrawEffect::NoPixelSnapping | ESlateDrawEffect::DisabledEffect,
		Color,
		true,
		3 * InParams.Geometry.Scale);

	FSlateDrawElement::MakeLines(
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToOffsetPaintGeometry(FVector2D(0, 34)),
		LinePoints,
		InParams.bEnabled ? ESlateDrawEffect::NoPixelSnapping : ESlateDrawEffect::NoPixelSnapping | ESlateDrawEffect::DisabledEffect,
		Color,
		true,
		4 * InParams.Geometry.Scale);
#pragma endregion
	return InParams.Layer;

}


int32 SSlateDemoSlateDrawPaintWidget::TestRotation(const FOnPaintHandlerParams& InParams)
{
	const FSlateBrush* StyleInfo = FCoreStyle::Get().GetBrush("FocusRectangle");

	FSlateDrawElement::MakeBox(//就是绘制画刷
		InParams.OutDrawElements,
		InParams.Layer,
		InParams.Geometry.ToPaintGeometry(),
		StyleInfo,
		InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect
	);

	MakeRotationExample(InParams);//绘制两个旋转图片一个自转,一个公转

	return InParams.Layer;
}

void SSlateDemoSlateDrawPaintWidget::MakeRotationExample(const FOnPaintHandlerParams& InParams)
{
	const FSlateBrush* CenterBrush = &ToolbarStyle->runimg;
	const FSlateBrush* TestBrush = &ToolbarStyle->runimg;

	const FVector2D LocalPos = FVector2D(30, 30);
	const FVector2D LocalSize = CenterBrush->ImageSize;

	FSlateLayoutTransform CenterLayoutTransform(LocalPos);
	
	// Make a box that rotates around its center.  Note if you don't specify the rotation point or rotation space
	// it defaults to rotating about the center of the box.  ERotationSpace::RelativeToElement is used by default in this case.  
	// If any rotation point is specified in that space, is relative to the element (0,0 is the upper left of the element)
	{
		FSlateDrawElement::MakeRotatedBox(//自转
			InParams.OutDrawElements,
			InParams.Layer,
			InParams.Geometry.ToPaintGeometry(LocalSize, CenterLayoutTransform),
			CenterBrush,
			InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
			CenterRotation);//CenterRotation
	}

	// Make a box that rotates around the center of the previous box
	{
		FSlateLayoutTransform OrbitLayoutTransform(LocalPos + LocalSize);
		const FVector2D LocalCenterOfRotation = (LocalPos + (LocalPos + LocalSize)) * .5f;
		const FVector2D RelativeOrbitPos = TransformPoint(Inverse(OrbitLayoutTransform), LocalCenterOfRotation);

		FSlateDrawElement::MakeRotatedBox(//公转
			InParams.OutDrawElements,
			InParams.Layer,
			InParams.Geometry.ToPaintGeometry(TestBrush->ImageSize, OrbitLayoutTransform),
			TestBrush,
			InParams.bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect,
			OuterRotation,
			RelativeOrbitPos);
	}
}

int32 SSlateDemoSlateDrawPaintWidget::TestCustomVerts(const FOnPaintHandlerParams& InParams)
{

	//获得一个笔刷
	const FSlateBrush* MyBrush = FCoreStyle::Get().GetBrush("ColorSpectrum.Spectrum");
	FSlateResourceHandle Handle = MyBrush->GetRenderingResource();


	//顶点数组
	TArray<FSlateVertex> vertexs;
	//渲染索引
	TArray<SlateIndex> indexs;

	//需要画的三个顶点
	FSlateVertex v1;
	FSlateVertex v2;
	FSlateVertex v3;
	FSlateVertex v4;


	vertexs.Add(v1);
	vertexs.Add(v2);
	vertexs.Add(v3);
	vertexs.Add(v4);
	//正方形要绘制的两组三角形
	TArray<SlateIndex> Indexes;
	for (int i = 1; i <= 2; ++i)
	{
		indexs.Add(0);
		indexs.Add(i);
		indexs.Add((i + 1 > 3) ? (1) : (i + 1));
	}

	//顶点的UV
	for (FSlateVertex& tempvertex : vertexs)
	{
		tempvertex.TexCoords[0] = 0.0f;
		tempvertex.TexCoords[1] = 0.0f;
		tempvertex.TexCoords[2] = 0.0f;
		tempvertex.TexCoords[3] = 0.0f;
		tempvertex.MaterialTexCoords = FVector2D(0.0f, 0.0f);
		tempvertex.PixelSize[0] = 0.0f;
		tempvertex.PixelSize[1] = 0.0f;
	}
	//给顶点颜色
	vertexs[0].Color = FColor::Blue;
	vertexs[1].Color = FColor::Red;
	vertexs[2].Color = FColor::Green;
	vertexs[3].Color = FColor::Yellow;

	//下面是给正方形四个顶点个顶点的位置
	vertexs[0].Position = FVector2D(50 + InParams.Geometry.AbsolutePosition.X, 50 + InParams.Geometry.AbsolutePosition.Y);
	vertexs[1].Position = FVector2D(50 + InParams.Geometry.AbsolutePosition.X, 500 + InParams.Geometry.AbsolutePosition.Y);
	vertexs[2].Position = FVector2D(300 + InParams.Geometry.AbsolutePosition.X, 500 + InParams.Geometry.AbsolutePosition.Y);
	vertexs[3].Position = FVector2D(300 + InParams.Geometry.AbsolutePosition.X, 50 + InParams.Geometry.AbsolutePosition.Y);
	//绘画函数，上面代码全是为了构造数据
	FSlateDrawElement::MakeCustomVerts(InParams.OutDrawElements, InParams.Layer, Handle, vertexs, indexs, nullptr, 0, 0);






	const float Radius = FMath::Min(InParams.Geometry.GetLocalSize().X, InParams.Geometry.GetLocalSize().Y) * 0.5f;
	const FVector2D Center = InParams.Geometry.AbsolutePosition + InParams.Geometry.GetLocalSize() * 0.5f;//要绘制图形的中点

	const FSlateBrush* MyBrush1 = FCoreStyle::Get().GetBrush("ColorWheel.HueValueCircle");

	FSlateResourceHandle Handle1 = MyBrush1->GetRenderingResource();
	const FSlateShaderResourceProxy* ResourceProxy = Handle1.GetResourceProxy();

	//UV的概念请看 https://blog.csdn.net/qq340635610/article/details/78568764
	FVector2D UVCenter = FVector2D::ZeroVector;
	FVector2D UVRadius = FVector2D(1, 1);
	if (ResourceProxy != nullptr)
	{
		UVRadius = 0.5f * ResourceProxy->SizeUV;
		UVCenter = ResourceProxy->StartUV + UVRadius;
	}

	// Make a triangle fan in the area allotted
	const int NumTris = 12;
	TArray<FSlateVertex> Verts;
	Verts.Reserve(NumTris * 3);//36个点共计12组三角形

	//下面这个图形是12边形,画12边形用了13个点,12个角和中心圆点
	// Center Vertex
	Verts.AddZeroed();//计算中心原点
	{
		FSlateVertex& NewVert = Verts.Last();
		NewVert.Position[0] = Center.X;//绘制坐标点
		NewVert.Position[1] = Center.Y;
		NewVert.TexCoords[0] = UVCenter.X;
		NewVert.TexCoords[1] = UVCenter.Y;
		NewVert.TexCoords[2] = NewVert.TexCoords[3] = 1.0f;
		NewVert.Color = FColor::White;
	}

	for (int i = 0; i < NumTris; ++i)
	{
		Verts.AddZeroed();
		{
			const float Angle = (2 * PI * i) / NumTris;
			const FVector2D EdgeDirection(FMath::Cos(Angle), FMath::Sin(Angle));
			const FVector2D Edge(Radius * EdgeDirection);
			FSlateVertex& NewVert = Verts.Last();
			NewVert.Position[0] = Center.X + Edge.X;
			NewVert.Position[1] = Center.Y + Edge.Y;
			NewVert.TexCoords[0] = UVCenter.X + UVRadius.X * EdgeDirection.X;
			NewVert.TexCoords[1] = UVCenter.Y + UVRadius.Y * EdgeDirection.Y;
			NewVert.TexCoords[2] = NewVert.TexCoords[3] = 1.0f;
			NewVert.Color = FColor::White;
		}
	}

	//下面的一共分为12组,这12组其实是12块三角形,每组3个坐标点
	TArray<SlateIndex> Indexes1;
	for (int i = 1; i <= 12; ++i)
	{
		Indexes1.Add(0);//圆心
		Indexes1.Add(i);//等腰三角形的两个地脚
		Indexes1.Add((i + 1 > 12) ? (1) : (i + 1));//等腰三角形的两个地脚
	}

	FSlateDrawElement::MakeCustomVerts(InParams.OutDrawElements, InParams.Layer, Handle1, Verts, Indexes1, nullptr, 0, 0);

	return InParams.Layer;
}